package com.my.study.utils;

import com.fasterxml.jackson.core.type.TypeReference;
import com.my.study.config.JwtConfig;
import com.my.study.entity.vo.UserInfoVO;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.Map;
import java.util.UUID;

public class JwtUtil {

    private static JwtConfig jwtConfig = SpringBeanUtil.getBean("jwtConfig",JwtConfig.class);

    /**
     * 创建token
     *
     * @param map 自定义信息的存储
     * @return 加密后的token字符串
     */
    public static String createToken(Map<String, Object> map) {
        JwtBuilder builder = Jwts.builder();
        if (!map.isEmpty()) {
            builder.setClaims(map);
        }
        SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
        // 生成JWT的时间
        long nowMillis = System.currentTimeMillis();
        // 设置jwt的body
        builder = Jwts.builder()
                .setClaims(map)
                .setId(UUID.randomUUID().toString())// 设置jti(JWT ID)：是JWT的唯一标识
                .setIssuedAt(new Date())// iat: jwt的签发时间
                .setSubject(String.valueOf(map.get("userName")))// 代表这个JWT的主体，即它的所有人，这个是一个json格式的字符串
                .signWith(signatureAlgorithm, jwtConfig.getSecret().getBytes(StandardCharsets.UTF_8));// 设置签名使用的签名算法和签名使用的秘钥
        if (jwtConfig.getExpire() >= 0) {
            long expMillis = nowMillis + jwtConfig.getExpire();
            Date exp = new Date(expMillis);
            // 设置过期时间
            builder.setExpiration(exp);
        }
        return builder.compact();
    }

    /**
     * Token的解密并且获取某个值
     *
     * @param token 加密后的token
     * @return
     */
    public static String parseJWT(String token, String key) {
        // 得到DefaultJwtParser
        Claims claims = Jwts.parser()
                .setSigningKey(jwtConfig.getSecret().getBytes(StandardCharsets.UTF_8))// 设置需要解析的jwt
                .parseClaimsJws(token).getBody();
        return claims.get(key).toString();
    }

    /**
     * Token的解密并且获取某个值
     *
     * @param token 加密后的token
     * @return
     */
    public static String getValue(String token, String key) {
        // 得到DefaultJwtParser
        Claims claims = Jwts.parser()
                .setSigningKey(jwtConfig.getSecret().getBytes(StandardCharsets.UTF_8))// 设置需要解析的jwt
                .parseClaimsJws(token).getBody();
        return claims.get(key).toString();
    }

    /**
     * Token的解密并且获取用户信息
     *
     * @param token 加密后的token
     * @return
     */
    public static UserInfoVO getUserInfo(String token) {
        // 得到DefaultJwtParser
        Claims claims = Jwts.parser()
                .setSigningKey(jwtConfig.getSecret().getBytes(StandardCharsets.UTF_8))// 设置需要解析的jwt
                .parseClaimsJws(token).getBody();
        return getUserInfo(claims);
    }

    /**
     * 校验token
     *
     * @param token
     * @return
     */
    public static boolean checkToken(String token) {
        try {
            Claims claims = Jwts.parser()
                    .setSigningKey(jwtConfig.getSecret().getBytes(StandardCharsets.UTF_8))
                    .parseClaimsJws(token)
                    .getBody();
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * 刷新token
     *
     * @param token
     */
    public static String refreshToken(String token) {
        String refreshedToken;
        try {
            final Claims claims = Jwts.parser()
                    .setSigningKey(jwtConfig.getSecret().getBytes(StandardCharsets.UTF_8))
                    .parseClaimsJws(token)
                    .getBody();
            refreshedToken = getJwtMap(claims);
        } catch (Exception e) {
            refreshedToken = null;
        }
        return refreshedToken;
    }

    /**
     * 获取信息重新封装
     *
     * @param claims
     * @return
     */
    public static String getJwtMap(Claims claims) {
        UserInfoVO userInfo = getUserInfo(claims);
        return createToken(JsonUtil.ObjectToEntity(userInfo, new TypeReference<Map>() {
        }));
    }

    /**
     * 获取用户信息
     *
     * @param claims
     * @return
     */
    public static UserInfoVO getUserInfo(Claims claims) {
        UserInfoVO userInfo = new UserInfoVO();
        userInfo.setUserId(claims.get("userId", String.class));
        userInfo.setUserName(claims.get("userName", String.class));
        userInfo.setDeptId(claims.get("deptId", String.class));
        userInfo.setDeptName(claims.get("deptName", String.class));
        return userInfo;
    }

    /**
     * 获取测试token
     *
     * @return
     */
    public static String getDefaultToken() {
        UserInfoVO userInfo = new UserInfoVO();
        userInfo.setUserId("test");
        userInfo.setUserName("testName");
        userInfo.setDeptId("testDeptId");
        userInfo.setDeptName("testDeptName");
        return createToken(JsonUtil.ObjectToEntity(userInfo, new TypeReference<Map>() {
        }));
    }
}
